use std::{collections::HashMap, sync::RwLock};

use crate::{
    datasource::RelationCondition,
    modeling::{
        application::{
            ApplicationConversation, ApplicationConversationMessage, InstalledApplication,
        },
        system::{
            appstore::{
                AppStoreApplication, AppStoreApplicationCategory, AppStoreApplicationVersion,
            },
            share::{SharedObject, SharedObjectRef, SharedObjectVersion},
            user::{SystemAccount, SystemUser},
        },
        workspace::{ProjectDomain, ProjectTask},
    },
};

use super::{
    assistant::{
        FormSchema, FormSchemaItem, Model, ModelProvider, ModelProviderSetting, ModelSetting,
        ModelTypeSetting,
    },
    persistence::ClassPersistenceGetter,
    scheduler::{SchedulerTask, SchedulerTaskResult, SchedulerTaskTemplate},
    tool::{
        Tool, ToolBody, ToolCategory, ToolCategoryMapping, ToolConfig, ToolProvider,
        ToolProviderConfig,
    },
    workflow::{WorkflowEntity, WorkflowFeature},
    workspace::{Project, ProjectApplication, ProjectApplicationConfig, ProjectConfig},
    Class, ClassAttribute, ClassGetter, ClassPersistence, ClassRelation, ClassRelationGetter,
    ClassTraits, DataSourceClassAttributeMapping, DataSourceClassMapping,
    DataSourceClassRelationMapping, DataSourceEntity, Domain, DomainDependency, NameSpace,
    Relation, Traits,
};

// 插入class
macro_rules! insert_classes {
    // 模式匹配
    ($map:expr, $($element:ident),+ $(,)?) => {
        $(
            $map.insert(
                $element::get_identifier().expect("初始Meta数据"),
                $element::get_class().expect("初始Meta数据"),
            );
        )+
    };
}

// 插入ClassPersistence
macro_rules! insert_class_persistence {
    // 模式匹配
    ($map:expr, $($element:ident),+ $(,)?) => {
        $(
            $map.insert(
                $element::get_identifier().expect("初始Meta数据"),
                $element::class_persistence().expect("初始Meta数据"),
            );
        )+
    };
}

// 插入ClassPersistence
macro_rules! class_items {
    // 模式匹配
    ($vec:expr, $($element:ident),+ $(,)?) => {
        $(
            $vec.push($element::get_class()?);
        )+
    };
}

// 插入ClassPersistence
macro_rules! class_relations_case {
    // 模式匹配
    ($class_identifier:expr, $condition:expr, $($element:ident),+ $(,)?) => {
        $(
            if $class_identifier == &$element::get_identifier()? {
                if let Some(condition) = $condition {
                    return $element::class_relations_by_condition(condition);
                } else {
                    return $element::class_relations();
                }
            }
        )+
    };
}

lazy_static::lazy_static! {

    pub(crate) static ref SYSTEM_CLASS_CACHE: RwLock<HashMap<String,Class>> = RwLock::new({
       let mut map =  HashMap::new();
       insert_classes!(map, Class, Domain, DomainDependency, NameSpace, Relation, Traits, DataSourceEntity, ClassAttribute, ClassTraits, ClassRelation);
       insert_classes!(map, DataSourceClassMapping, DataSourceClassAttributeMapping, DataSourceClassRelationMapping);
       insert_classes!(map, Model, ModelTypeSetting, ModelProvider,ModelSetting,ModelProviderSetting,FormSchema,FormSchemaItem);
       insert_classes!(map, WorkflowEntity, WorkflowFeature);
       insert_classes!(map, ToolProvider, Tool, ToolProviderConfig,ToolConfig,ToolBody,ToolCategory,ToolCategoryMapping);
       insert_classes!(map, Project, ProjectTask, ProjectDomain, ProjectConfig, ProjectApplication,ProjectApplicationConfig);
       insert_classes!(map, SchedulerTask, SchedulerTaskResult, SchedulerTaskTemplate);
       insert_classes!(map, InstalledApplication, ApplicationConversation, ApplicationConversationMessage);
       insert_classes!(map, SystemUser, SystemAccount, SharedObject, SharedObjectVersion, SharedObjectRef);
       insert_classes!(map, AppStoreApplication, AppStoreApplicationCategory, AppStoreApplicationVersion);
       map
    });

    pub(crate) static ref SYSTEM_CLASS_PERSISTENCE_CACHE: RwLock<HashMap<String,Option<ClassPersistence>>> = RwLock::new({
        let mut map =  HashMap::new();
        insert_class_persistence!(map, Class, Domain, DomainDependency, NameSpace, Relation, Traits, DataSourceEntity, ClassAttribute, ClassTraits, ClassRelation);
        insert_class_persistence!(map, DataSourceClassMapping, DataSourceClassAttributeMapping, DataSourceClassRelationMapping);
        insert_class_persistence!(map, Model, ModelTypeSetting, ModelProvider,ModelSetting,ModelProviderSetting,FormSchema,FormSchemaItem);
        insert_class_persistence!(map, WorkflowEntity, WorkflowFeature);
        insert_class_persistence!(map, ToolProvider, Tool, ToolProviderConfig,ToolConfig,ToolBody,ToolCategory,ToolCategoryMapping);
        insert_class_persistence!(map, Project, ProjectTask, ProjectDomain, ProjectConfig, ProjectApplication,ProjectApplicationConfig);
        insert_class_persistence!(map, SchedulerTask, SchedulerTaskResult, SchedulerTaskTemplate);
        insert_class_persistence!(map, InstalledApplication, ApplicationConversation, ApplicationConversationMessage);
        insert_class_persistence!(map, SystemUser, SystemAccount, SharedObject, SharedObjectVersion, SharedObjectRef);
        insert_class_persistence!(map, AppStoreApplication, AppStoreApplicationCategory, AppStoreApplicationVersion);
        map
    });
}

pub const SYSTEM_DOMAIN_IDENTIFIER: &'static str = "_g01_meta";

pub fn get_meta_classes() -> anyhow::Result<Vec<Class>> {
    let mut vec = vec![];
    //
    class_items!(
        vec,
        Class,
        Domain,
        DomainDependency,
        NameSpace,
        Relation,
        Traits,
        DataSourceEntity,
        ClassAttribute,
        ClassRelation,
        ClassTraits,
        DataSourceClassMapping,
        DataSourceClassAttributeMapping,
        DataSourceClassRelationMapping,
        //
        Model,
        ModelTypeSetting,
        ModelProvider,
        ModelSetting,
        ModelProviderSetting,
        FormSchema,
        FormSchemaItem,
        //
        WorkflowEntity,
        WorkflowFeature,
        ToolProvider,
        Tool,
        ToolProviderConfig,
        ToolConfig,
        ToolBody,
        ToolCategory,
        ToolCategoryMapping,
        //
        Project,
        ProjectTask,
        ProjectDomain,
        ProjectConfig,
        ProjectApplication,
        ProjectApplicationConfig,
        SchedulerTask,
        SchedulerTaskResult,
        SchedulerTaskTemplate,
        //
        InstalledApplication,
        ApplicationConversation,
        ApplicationConversationMessage,
        //
        SystemUser,
        SystemAccount,
        SharedObject,
        SharedObjectVersion,
        SharedObjectRef,
        //
        AppStoreApplication,
        AppStoreApplicationCategory,
        AppStoreApplicationVersion,
    );
    Ok(vec)
}

pub fn get_meta_class(class_identifier: &String) -> anyhow::Result<Class> {
    if let Some(c) = SYSTEM_CLASS_CACHE
        .read()
        .map_err(|err| anyhow::anyhow!("{}", err))?
        .get(class_identifier)
    {
        Ok(c.clone())
    } else {
        Err(anyhow::anyhow!("没有找到:{}", class_identifier))
    }
}

pub fn get_meta_class_persistence(
    class_identifier: &String,
) -> anyhow::Result<Option<ClassPersistence>> {
    if let Some(c) = SYSTEM_CLASS_PERSISTENCE_CACHE
        .read()
        .map_err(|err| anyhow::anyhow!("{}", err))?
        .get(class_identifier)
    {
        Ok(c.clone())
    } else {
        Err(anyhow::anyhow!("没有找到:{}", class_identifier))
    }
}

pub fn get_meta_class_relations(
    class_identifier: &String,
    condition: &Option<RelationCondition>,
) -> anyhow::Result<Vec<ClassRelation>> {
    if let Some(c) = SYSTEM_CLASS_CACHE
        .read()
        .map_err(|err| anyhow::anyhow!("{}", err))?
        .get(class_identifier)
    {
        //
        class_relations_case!(
            class_identifier,
            condition,
            Class,
            Domain,
            DomainDependency,
            NameSpace,
            Relation,
            Traits,
            DataSourceEntity,
            ClassAttribute,
            ClassRelation,
            ClassTraits,
            DataSourceClassMapping,
            DataSourceClassAttributeMapping,
            DataSourceClassRelationMapping,
            //
            Model,
            ModelTypeSetting,
            ModelProvider,
            ModelSetting,
            ModelProviderSetting,
            FormSchema,
            FormSchemaItem,
            //
            WorkflowEntity,
            WorkflowFeature,
            ToolProvider,
            Tool,
            ToolProviderConfig,
            ToolConfig,
            ToolBody,
            ToolCategory,
            ToolCategoryMapping,
            //
            Project,
            ProjectTask,
            ProjectDomain,
            ProjectConfig,
            ProjectApplication,
            ProjectApplicationConfig,
            SchedulerTask,
            SchedulerTaskResult,
            SchedulerTaskTemplate,
            //
            InstalledApplication,
            ApplicationConversation,
            ApplicationConversationMessage,
            //
            SystemUser,
            SystemAccount,
            SharedObject,
            SharedObjectVersion,
            SharedObjectRef,
            //
            AppStoreApplication,
            AppStoreApplicationCategory,
            AppStoreApplicationVersion,
        );

        Err(anyhow::anyhow!("没有找到:{}", class_identifier))
    } else {
        Err(anyhow::anyhow!("没有找到:{}", class_identifier))
    }
}
